﻿using System.IO;
using System.Text;
using HexunMicroblogging.Schema;
using MicrobloggingInterface;

namespace HexunMicroblogging
{
    public class HexunMBImp : IMicroblogging
    {
        #region Private fields

        private Issue issuer;

        private struct ConfigFile
        {
            /// <summary>
            /// Configure file name.
            /// </summary>
            public string name;

            /// <summary>
            /// Configure file full path.
            /// </summary>
            public string fullPath;

            /// <summary>
            /// Configure file's XSD file's full path
            /// </summary>
            public string xsdPath;
        }

        /// <summary>
        /// Error message.
        /// </summary>
        private string errorMessage { get; set; }

        /// <summary>
        /// Response type.
        /// </summary>
        private string responseContent { get; set; }

        /// <summary>
        /// Response content.
        /// </summary>
        private DataType responseType { get; set; }

        #endregion

        #region Private methods

        /// <summary>
        /// Initialize and the configure of microblogging client tool.
        /// </summary>
        /// <returns>True for success, false otherwise.</returns>
        private bool InitConfig()
        {
            // Validate schema of configure file.
            if (!SchemaValidate(ReadXml(configFile.xsdPath), ReadXml(configFile.fullPath)))
            {
                return false;
            }

            // Load and read configure file.
            issuer = new Issue(configFile.name);
            if (!issuer.LoadConfig())
            {
                return false;
            }

            return true;
        }

        #region Helper methods

        /// <summary>
        /// Simple helper method reading an file from disk and
        /// returning the content as a string.
        /// </summary>
        /// <param name="fileName">The relative path to the file you want to read.</param>
        /// <returns>The file content.</returns>
        private string ReadXml(string fileName)
        {
            using (StreamReader reader = new StreamReader(fileName, Encoding.Default))
            {
                return reader.ReadToEnd();
            }
        }

        /// <summary>
        /// Validate if the configure file match the XSD rule.
        /// </summary>
        /// <param name="schema">Schema.</param>
        /// <param name="xmlData">Xml for validate.</param>
        /// <returns>Validate result, true for success, false otherwise.</returns>
        private bool SchemaValidate(string schema, string xmlData)
        {
            SchemaValidation validator = new SchemaValidation(schema);
            return validator.ValidateSchema(xmlData) == ValidationResult.Success;
        }

        #endregion

        #endregion

        public HexunMBImp()
        {
            // Set configure file's name, full path and XSD path.
            configFile.name = System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name.Replace(".dll", ".config");
            configFile.fullPath = System.Reflection.Assembly.GetExecutingAssembly().Location.Replace(".dll", ".config");
            configFile.xsdPath = configFile.fullPath.Replace(".config", ".xsd");
        }

        /// <summary>
        /// ConfigFile's instance.
        /// </summary>
        ConfigFile configFile;

        /// <summary>
        /// Get last error message.
        /// </summary>
        /// <returns>Error message text.</returns>
        public string GetLastError()
        {
            return errorMessage;
        }

        /// <summary>
        /// Get response content.
        /// </summary>
        /// <returns>Response content.</returns>
        public string GetResponseContent()
        {
            return this.responseContent;
        }

        /// <summary>
        /// Get response type.
        /// </summary>
        /// <returns>Response type.</returns>
        public DataType GetResponseType()
        {
            return this.responseType;
        }

        /// <summary>
        /// Issue a micro-blogging message.
        /// </summary>
        /// <returns>Issue result, true for success, false otherwise.</returns>
        public bool Issue(string userName, string password, string content)
        {
            // If set configure error, return false.
            if (!InitConfig())
            {
                errorMessage = "Initialize configure file failed.";
                return false;
            }

            if (issuer.NeedCredential)
            {
                issuer.SetCredential(userName, password);
            }

            string issueErrorMessage = string.Empty;
            if (!issuer.DoIssue(content, out issueErrorMessage))
            {
                errorMessage = issueErrorMessage;
                return false;
            }

            this.responseContent = issuer.ResponseContent;
            this.responseType = issuer.ResponseDataType;
            
            return true;
        }
    }
}
